package com.suray.wcs.web.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suray.basic.wcs.node.WCSNodeModule;
import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.core.api.impl.RouteFactoryImp;
import com.suray.basic.wcs.path.enums.DirectionStatus;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.plc.pojo.oper.lifter.LifterOper;
import com.suray.basic.wcs.plc.utils.PlcUnit;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.ModuleType;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.annotation.Log;
import com.suray.commin.core.controller.BaseController;
import com.suray.commin.core.controller.ResponseData;
import com.suray.commin.core.page.TableDataInfo;
import com.suray.commin.core.utils.FileUtils;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.commin.enmus.BusinessType;
import com.suray.rgv.*;
import com.suray.rgv.instance.RgvInstance;
import com.suray.wcs.res.enums.Order;
import com.suray.wcs.res.enums.RgvStatus;
import com.suray.wcs.res.enums.RgvType;
import com.suray.wcs.service.core.util.CommonUtil;
import com.suray.wcs.service.core.util.LockFloorManager;
import com.suray.wcs.service.core.util.LockNodeManager;
import com.suray.wcs.service.enums.*;
import com.suray.commin.exception.OrderExecuteException;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.pojo.*;
import com.suray.wcs.service.pojo.rgv.extract.log.RgvExtractLog;
import com.suray.wcs.service.pojo.rgv.move.speed.RgvMoveBySpeedThread;
import com.suray.wcs.service.rescontact.MapRgvDirection;
import com.suray.wcs.service.rescontact.ToRes;
import com.suray.wcs.service.rescontact.WolAndShutdown;
import com.suray.wcs.service.system.bo.DistRGVStatusBO;
import com.suray.wcs.service.system.entity.NodeDB;
import com.suray.wcs.service.system.entity.RgvDB;
import com.suray.wcs.service.system.entity.TaskDB;
import com.suray.wcs.service.system.entity.WareHouseDB;
import com.suray.wcs.service.system.service.IWareHouseDBService;
import com.suray.wcs.service.system.service.impl.*;
import com.suray.wcs.service.util.WcsUtil;
import com.suray.wcs.web.system.controller.thread.WriteMapUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("/rgvdb")
@CrossOrigin(value = "*", allowCredentials = "true")
public class RgvDBController extends BaseController {
    @Autowired
    private RgvDBServiceImpl rgvdbService;
    @Autowired
    private NodeDBServiceImpl nodedbServiceImpl;

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private DeviceManagerServiceImpl deviceManagerService;

    @Autowired
    private TaskDBServiceImpl taskdbService;

    @Autowired
    private IWareHouseDBService WareHouseDBService;
    @Autowired
    private NetAddressManageDBServiceImpl devicedbServiceImpl;

    /**
     * 查询小车信息
     *
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:query')")
    @GetMapping(value = "/queryRgvInfo")
    @ApiOperation(value = "查询小车信息")
    public TableDataInfo queryRgvInfo(RgvDB rgvdb) {
        startPage();
        List<RgvDB> rgvList = deviceManagerService.getRgvList(rgvdb);
        return getDataTable(rgvList);
    }

    /**
     * 重分任务
     *
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:resendRgvTask')")
    @Log(title = "车辆管理", method = "重分任务", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/resendRgvTask")
    @ApiOperation(value = "重分任务")
    public ResponseData resendRgvTask(RgvDB rgvdb) {
        List<TaskDB> taskDBS = taskdbService.getRgvUnToStartTask(rgvdb);
        if (CollectionUtils.isNotEmpty(taskDBS)) {
            HashSet<TaskDB> removeTaskSet = new HashSet<>();
            taskDBS.stream().forEach(task -> {
                if (task.getRgvProgress().getProgressNum() < TaskRgvProgress.RGV_TO_START.getProgressNum()) {
                    removeTaskSet.add(task);
                }
            });
            removeTaskSet.forEach(task -> {
                if (task.getPriorityCode() != null && CommonUtil.PRIORITY_CODE_AVOID.equals(task.getPriorityCode())
                        || task.getTaskType().getTypeNum() == TaskType.CHARGE.getTypeNum() || task.getTaskType() == TaskType.MOVE_UNLOADED) {
                    taskdbService.updateTaskStatus(task, TaskStatus.FINISH);
                    String value = Plc.PLC_INTERRUPT_CACHE.get(String.valueOf(task.getTaskId()));
                    if (!StringUtils.isEmpty(value)) {
                        Plc.PLC_INTERRUPT_CACHE.remove(String.valueOf(task.getTaskId()));
                    }
                } else {
                    taskdbService.updateTaskProcessingRgvNoAndPreProcessingRgvNo(task, null, null, TaskRgvProgress.NOT_ASSIGNED_TO_RGV);
                }
            });
        }
        return ResponseData.success("重发成功");
    }

    @PreAuthorize("@ss.hasPermi('rgvdb:edit')")
    @Log(title = "车辆管理", method = "修改小车信息", businessType = BusinessType.UPDATE)
    @PostMapping(value = "/updateRgvInfo")
    @ApiOperation(value = "修改小车信息")
    public ResponseData updateRgvInfo(@Validated @RequestBody RgvDB rgvDB) {
        if (rgvdbService.checkRgvNoUnique(rgvDB)) {
            return ResponseData.error("车辆编号为" + rgvDB.getRgvNo() + "的小车已经存在");
        }
        RgvDB rgvdb = rgvdbService.getRgvDBByNo(rgvDB.getRgvNo());
        if (rgvdb == null) {
            return ResponseData.error("该小车不存在");
        }
        // 位置判重
        if (deviceManagerService.checkRgvLocation(rgvDB)) {
            return ResponseData.error(rgvDB.getLocation() + "位置已存在车辆，换个位置试试");
        }
        // 缓存位置判重
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(rgvDB.getFreeLocation()) && deviceManagerService.checkRgvFreeLocation(rgvDB)) {
            return ResponseData.error(rgvDB.getFreeLocation() + "缓存位置已绑定其他车辆，换个位置试试");
        }
        // 位置是否可停车
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(rgvDB.getLocation()) && !nodedbServiceImpl.checkRgvNodeCanStop(rgvDB.getLocation())) {
            return ResponseData.error(rgvDB.getLocation() + "位置不可停车，换个位置试试");
        }
        // 缓存位是否可停车
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(rgvDB.getFreeLocation()) && !nodedbServiceImpl.checkRgvNodeCanStop(rgvDB.getFreeLocation())) {
            return ResponseData.error(rgvDB.getFreeLocation() + "缓存位置不可停车，换个位置试试");
        }
        try {
            if (deviceManagerService.updateRgv(rgvDB)) {
                Node node = Node.parseGrid(rgvdb.getLocation());
                Node newNode = Node.parseGrid(rgvDB.getLocation());
                Rgv rgv = SystemInit.getByRgvNo(rgvDB.getRgvNo());

                try {
                    if (rgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                        ((Rgv60) rgv).getRgvCore().initNet(rgvDB.getRgvIp(), 0);
                        if (rgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
                            ((RgvSM) rgv).getRgvCore().setSonGroundCodeInMother(rgvDB.getSonRgvGroundCodeInMother());
                            if (!rgvdb.getMappedSonRgv().equals(rgvDB.getMappedSonRgv())) {
                                SystemInit.changeRgvSMSonRgv((RgvSM) rgv, rgvDB);
                            }
                        } else if (rgv.checkRgvType(RgvType.RGV_FORK)) {
                            ((RgvFork) rgv).resetForkParam();
                        }
                    }
                } catch (ClassCastException e) {
                    WcsFuncUtil.exceptionLog(e, this.getClass());
                }

                if (rgv != null) {
                    if (!node.equals(newNode)) {
                        Set<Coord> oldLockNode = new HashSet<>();
                        oldLockNode.addAll(nodedbServiceImpl.getLinkedNode(node));
                        oldLockNode.removeAll(nodedbServiceImpl.getLinkedNode(newNode));
                        LockNodeManager.removeLockedNodes(oldLockNode, rgv);
                    }
                }
                return ResponseData.success(rgvDB.getRgvNo() + "号小车修改成功");
            } else {
                return ResponseData.error(rgvDB.getRgvNo() + "号小车修改失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseData.error(rgvDB.getRgvNo() + "号小车修改失败");
        }
    }


    @Log(title = "车辆管理", method = "修改小车信息启用自充跨层校准", businessType = BusinessType.UPDATE)
    @PostMapping(value = "/updateRgvInfoPart")
    @ApiOperation(value = "修改小车信息启用自充跨层校准")
    public ResponseData updateRgvInfoPart(@RequestBody RgvDB rgvdb) {
        try {
            Rgv curRgv;
            curRgv = SystemInit.getByRgvNo(rgvdb.getRgvNo());
            if (rgvdb.getOnline() != null) {
                curRgv.getRgvDB().setOnline(rgvdb.getOnline());
            }
            if (rgvdb.getIsPassFloor() != null) {
                curRgv.getRgvDB().setIsPassFloor(rgvdb.getIsPassFloor());
            }
            if (rgvdb.getIsAutoCharge() != null) {
                curRgv.getRgvDB().setIsAutoCharge(rgvdb.getIsAutoCharge());
            }
            if (rgvdb.getIsCalibration() != null) {
                curRgv.getRgvDB().setIsCalibration(rgvdb.getIsCalibration());
            }
            if (rgvdb.getBalanceBat() != null) {
                curRgv.getRgvDB().setBalanceBat(rgvdb.getBalanceBat());
            }

            boolean flag = deviceManagerService.updateById(curRgv.getRgvDB());
            if (flag) {
                return ResponseData.success("修改成功");
            } else {
                return ResponseData.error("修改失败");
            }
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvdb.getRgvNo() + " 的小车不存在", null);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseData.error("修改失败");
        }
    }

    /**
     * 添加小车
     *
     * @param rgvDB
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:add')")
    @Log(title = "车辆管理", method = "新增小车数据", businessType = BusinessType.INSERT)
    @PostMapping(value = "/insertRgvInfo")
    @ApiOperation("新增小车数据")
    public ResponseData insertRgvInfo(@Validated @RequestBody RgvDB rgvDB) {
        if (rgvdbService.checkRgvNoUnique(rgvDB)) {
            return ResponseData.error("车辆编号为" + rgvDB.getRgvNo() + "的小车已经存在");
        }
        try {
            Node newAddRgvLocation = Node.parseGrid(rgvDB.getLocation());
            QueryWrapper<RgvDB> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(RgvDB::getLocation, newAddRgvLocation.toString());
            QueryWrapper<NodeDB> nodedbQueryWrapper = new QueryWrapper<>();
            nodedbQueryWrapper.lambda().eq(NodeDB::getGridx, newAddRgvLocation.getX()).eq(NodeDB::getGridy, newAddRgvLocation.getY()).eq(NodeDB::getGridz, newAddRgvLocation.getZ());
            List<NodeDB> nodeDBS = nodedbServiceImpl.list(nodedbQueryWrapper);
            if (nodeDBS.isEmpty()) {
                return ResponseData.error("位置不存在");
            } else {
                if (nodeDBS.get(0).getGridType().equals(NodeType.B)) {
                    return ResponseData.error("不可新增小车至禁用位置，换个位置试试");
                }
            }
            int size = deviceManagerService.count(queryWrapper);
            if (size > 0) {
                return ResponseData.error(rgvDB.getLocation() + "位置已存在车辆，换个位置试试");
            }
            if (LockNodeManager.checkNodesLocked(newAddRgvLocation)) {
                return ResponseData.error(rgvDB.getLocation() + "位置已被占用，换个位置试试");
            }
        } catch (Exception e) {
            return ResponseData.error("小车坐标位置格式不合法");
        }
        if (deviceManagerService.add(rgvDB)) {
            return ResponseData.success(rgvDB.getRgvNo() + "号小车添加成功");
        } else {
            return ResponseData.error(rgvDB.getRgvNo() + "号小车添加失败");
        }
    }

    /**
     * 切换小车自动充电
     */
    @Log(title = "车辆管理", method = "修改小车自动充电", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/autoChargeSwitch", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "修改小车自动充电")
    public ResponseData autoChargeSwitch(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车", null);
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在", null);
        }
        log.info("接收到修改 " + rgvNo + " 号小车自动充电指令");
        if (curRgv.getRgvDB().getIsAutoCharge()) {
            curRgv.getRgvDB().setIsAutoCharge(false);
        } else if (!curRgv.getRgvDB().getIsAutoCharge()) {
            curRgv.getRgvDB().setIsAutoCharge(true);
        }
        rgvdbService.updateById(curRgv.getRgvDB());
        return ResponseData.success("小车自动充电修改完成", curRgv);
    }

    /**
     * 发送地图
     *
     * @param rgvNo
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:sendMap')")
    @Log(title = "车辆管理", method = "发送地图", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/sendMap", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "发送地图")
    public ResponseData sendMap(@RequestParam Integer rgvNo) {
        WareHouseDB curWareHouseDB = WareHouseDBService.getCurWareHouseDB();
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在！");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线！");
        }
        if (curRgv.getRgvStatus() != RgvStatus.READY) {
            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                if (curRgv.getRgvStatus() == RgvStatus.UNKNOWN) {
                    return ResponseData.error("设备号为 " + rgvNo + " 的小车没有控制权！");
                }
            } else {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车未就绪！");
            }
        }

        if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
            try {
                Rgv60 rgv = (Rgv60) curRgv;
                String paperFilePath = WcsFuncUtil.getPaperFilePath(ModuleType.RGV_60, curWareHouseDB.getWarehouseName());
                String mapPath = paperFilePath + File.separator + "wcs_map";
                rgv.getRgvCore().sendMap(mapPath);
            } catch (IOException e) {
                WcsFuncUtil.exceptionLog(e, this.getClass());
                return ResponseData.error("地图下发 " + curRgv.getRgvName() + " 失败，通讯异常");
            } catch (Exception e) {
                WcsFuncUtil.exceptionLog(e, this.getClass());
                return ResponseData.error("地图下发 " + curRgv.getRgvName() + " 失败，错误原因:" + e.getMessage());
            }
        } else {
            ToRes toRes = ToRes.getInstance(curRgv);
            String name = "ResPlus";
            String paperFile = System.getProperty("user.dir") + File.separator + "wcs_map" + File.separator +
                    curWareHouseDB.getWarehouseName() + File.separator;
            //创建文件夹
            String filename = null;
            if (RgvType.FOUR_GENERATIONS.getValue() == curRgv.getRgvDB().getRgvType()) {
                filename = paperFile + name + ".7z";
            } else if (curRgv.checkRgvType(RgvType.FIVE_POINT_FOUR_TL)) {
                filename = paperFile + name + ".map";
            }
            RgvStatus rgvStatus = curRgv.getRgvStatus();
            try {
                //先发送地图指令，再传递地图文件
                WriteMapUtil.generalMap();
                toRes.sendMap(null);
                curRgv.setRgvStatus(RgvStatus.SEND_MAP);
                curRgv.setStopHeart(true);
                toRes.mapSend(null, filename);
            } catch (OrderExecuteException e) {
                return ResponseData.error("地图下发 " + curRgv.getRgvName() + " 失败，错误原因:" + e.getMessage());
            } catch (IOException e) {
                return ResponseData.error("地图下发 " + curRgv.getRgvName() + " 失败，与RES通讯异常");
            } finally {
                curRgv.setStopHeart(false);
            }
        }
        return ResponseData.success("地图发送成功");

    }

    /**
     * 修改充电位置 需要考虑充电桩被其他车占有的情况吗？
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:editCharge')")
    @Log(title = "车辆管理", method = "修改充电位置", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/editCharge", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "修改充电位置")
    public ResponseData editCharge(@RequestParam Integer rgvNo, @RequestParam String nodeId) {
        Rgv curRgv;
        NodeDB nodedb;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (nodeId == null) {
            return ResponseData.error("尚未标记位置, 不能修改");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        log.info("接收到 " + rgvNo + " 号小车修改充电位置至 " + nodeId + " 指令");
        nodedb = nodedbServiceImpl.getById(nodeId);
        if (nodedb == null) {
            return ResponseData.error("位置信息： " + nodeId + "  不存在");
        }
        if (!nodedb.getGridType().equals(NodeType.C)) {
            return ResponseData.error("标记位置不是充电桩，不可修改");
        }
        com.suray.basic.wcs.path.core.Node node = new Node(nodedb.getGridx(), nodedb.getGridy(), nodedb.getGridz());
        curRgv.getRgvDB().setChargeLocation(node.toString());
        rgvdbService.updateById(curRgv.getRgvDB());
        return ResponseData.success("小车充电位置修改完成");
    }

    /**
     * 修改缓存位置
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:editFreeLoca')")
    @Log(title = "车辆管理", method = "修改缓存位置", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/editFreeLoca", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "修改缓存位置")
    public ResponseData editFreeLoca(@RequestParam Integer rgvNo, @RequestParam String nodeId) {
        Rgv curRgv;
        NodeDB nodedb;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (nodeId == null) {
            return ResponseData.error("尚未标记位置, 不能修改");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        log.info("接收到 " + rgvNo + " 号小车修改缓存位置至 " + nodeId + " 指令");
        nodedb = nodedbServiceImpl.getById(nodeId);
        if (nodedb == null) {
            return ResponseData.error("位置信息： " + nodeId + "  不存在");
        }
        if (!nodedb.getCanToStop() || NodeType.B.equals(nodedb.getGridType())) {
            return ResponseData.error("标记位置是不可停车位置或禁用位置");
        }
        com.suray.basic.wcs.path.core.Node node = new Node(nodedb.getGridx(), nodedb.getGridy(), nodedb.getGridz());
        curRgv.getRgvDB().setFreeLocation(node.toString());
        rgvdbService.updateById(curRgv.getRgvDB());
        return ResponseData.success("小车充电位置修改完成");
    }

    /**
     * 清空缓存位置
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:clearFreeLoca')")
    @Log(title = "车辆管理", method = "清空缓存位置", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/clearFreeLoca", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "清空缓存位置")
    public ResponseData clearFreeLoca(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        log.info("接收到 " + rgvNo + " 号小车清空缓存位置的指令");
        curRgv.getRgvDB().setFreeLocation("");
        rgvdbService.updateById(curRgv.getRgvDB());
        return ResponseData.success("小车缓存位置清空完成");
    }

    /*
     * 	手动校准
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:editManual')")
    @Log(title = "车辆管理", method = "手动校准", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/editManual", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "手动校准")
    public ResponseData editManual(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行手动校准指令，请稍后重试");
        }
        log.info("接收到手动校准 " + rgvNo + " 号小车的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.manualCalibration(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error("手动校准 " + curRgv.getRgvName() + " 失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success("小车校准完成");
    }

    /*
     * 	远程唤醒开机
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:wolRgv')")
    @Log(title = "车辆管理", method = "远程唤醒开机", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/wolRgv", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "远程唤醒开机")
    public ResponseData wolRgv(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvDB().getRgvBaIp() == null) {
            return ResponseData.error("小车的广播地址为空");
        }
        if (curRgv.getRgvDB().getRgvMac() == null) {
            return ResponseData.error("小车的MAC地址为空");
        }
        if (curRgv.getRgvDB().getRgvPort() == null) {
            return ResponseData.error("小车的端口为空");
        }
        log.info("接收到远程唤醒 " + rgvNo + " 号小车的开机指令");
        return WolAndShutdown.wol(curRgv.getRgvDB().getRgvBaIp(), curRgv.getRgvDB().getRgvMac(), curRgv.getRgvDB().getRgvPort());
    }

    /*
     * 	远程关机
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:shutdownRgv')")
    @Log(title = "车辆管理", method = "远程关机", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/shutdownRgv", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "远程关机")
    public ResponseData shutdownRgv(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        log.info(rgvNo + "号车远程关机");
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvDB().getRgvType() == RgvType.FOUR_GENERATIONS.getValue()) {
            if (curRgv.getRgvDB().getRgvIp() == null) {
                return ResponseData.error("小车的IP地址为空");
            }
            log.info("接收到远程 " + rgvNo + " 号小车的关机指令");
            try {
                System.err.println(curRgv.getRgvDB().getRgvIp());
                WolAndShutdown.shutdown(curRgv.getRgvDB().getRgvIp());
            } catch (IllegalStateException e) {
                return ResponseData.success(rgvNo + "小车关机失败");
            }
        } else if (curRgv.checkRgvType(RgvType.FIVE_POINT_FOUR_TL)) {
            ToRes toRes = ToRes.getInstance(curRgv);
            toRes.shutDown(null);
        }
        return ResponseData.success(curRgv.getRgvDB().getRgvIp() + "小车关机完成");
    }

    /**
     * 清空有货任务
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:editCharge')")
    @Log(title = "车辆管理", method = "清除有货任务", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/clearTask", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "清除有货任务")
    public ResponseData clearTask(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (StringUtils.isEmpty(curRgv.getCargoTaskId())) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不需要清除有货任务");
        }
        curRgv.setCargoTaskId(null);
        rgvdbService.updateById(curRgv.getRgvDB());
        return ResponseData.success("小车清除有货任务完成");
    }

    /*
     * 	远程重启
     */
    @Log(title = "车辆管理", method = "远程重启", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/awakenRgv", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "远程重启")
    public ResponseData awakenRgv(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        log.info(rgvNo + "号车远程唤醒");
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvDB().getRgvType() == RgvType.FOUR_GENERATIONS.getValue()) {
            if (curRgv.getRgvDB().getRgvIp() == null) {
                return ResponseData.error("小车的IP地址为空");
            }
            log.info("接收到远程 " + rgvNo + " 号小车的重启指令");
            try {
                WolAndShutdown.restart(curRgv.getRgvDB().getRgvIp());
            } catch (IllegalStateException e) {
                return ResponseData.success(rgvNo + "小车重启失败");
            }
        } else if (curRgv.checkRgvType(RgvType.FIVE_POINT_FOUR_TL)) {
            ToRes toRes = ToRes.getInstance(curRgv);
            toRes.wakeUp(null);
        }
        return ResponseData.success("小车重启完成");
    }

    /*
     * 获取小车信息
     */
    @RequestMapping(value = "/getRgvByNo/{rgvNo}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "查询小车信息")
    public ResponseData getRgvByNo(@PathVariable Integer rgvNo) {
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        RgvDB rgvDBByNo = rgvdbService.getRgvDBByNo(rgvNo);
        rgvDBByNo.setXRegionList(Arrays.asList((Integer[]) ConvertUtils.convert(rgvDBByNo.getXRegion().split("-"), Integer.class)));
        rgvDBByNo.setYRegionList(Arrays.asList((Integer[]) ConvertUtils.convert(rgvDBByNo.getYRegion().split("-"), Integer.class)));
        rgvDBByNo.setZRegionList(Arrays.asList((Integer[]) ConvertUtils.convert(rgvDBByNo.getZRegion().split("-"), Integer.class)));
        return ResponseData.success("小车信息查询完成", rgvDBByNo);
    }

    /**
     * 按速度行驶
     *
     * @param rgvNo
     * @param speed
     * @param direction
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:speedRun')")
    @Log(title = "车辆管理", method = "按速度行驶", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/speedRun", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "按速度行驶")
    public ResponseData speedRun(@RequestParam String rgvNo, @RequestParam Integer speed,
                                 @RequestParam Integer direction) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (speed == null) {
            return ResponseData.error("速度不能为空");
        }
        if (direction == null) {
            return ResponseData.error("方向不能为空");
        }
        if (direction != 1 && direction != 2 && direction != 3 && direction != 4) {
            return ResponseData.error(direction + " 方向不存在");
        }
        if (speed > 10000 || speed < 0) {
            return ResponseData.error("速度不合法");
        }

        try {
            curRgv = SystemInit.getByRgvNo(Integer.parseInt(rgvNo));
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行按速度行驶指令，请稍后重试");
        }
        if ((direction == 1 || direction == 3) && curRgv.getDirectionStatus() == DirectionStatus.PD_24) {
            return ResponseData.error("小车当前为坡道，请换向后重试");
        }
        if ((direction == 2 || direction == 4) && curRgv.getDirectionStatus() == DirectionStatus.XD_13) {
            return ResponseData.error("小车当前为巷道，请换向后重试");
        }
        log.info("接收到按 " + speed + " 速度，方向 " + direction + " 行驶 " + rgvNo + " 号小车的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.runWithSpeed(null, direction, speed);
        } catch (OrderExecuteException e) {
            return ResponseData.error("按速度 " + speed + " ，方向 " + direction + " 行驶 " + curRgv.getRgvName() + " 失败原因:" + e.getMessage());
        }
        return ResponseData.success("小车按速度行驶指令发送成功", null);
    }

    /**
     * 按速度行驶按照规定速度行驶100
     *
     * @param rgvNo
     * @param direction
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:speedRun')")
    @Log(title = "车辆管理", method = "按速度行驶", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/speedGo", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "按速度行驶")
    public ResponseData speedGo(@RequestParam String rgvNo,
                                @RequestParam Integer direction) {
        try {
            log.info("按速度行驶");
            Rgv curRgv;
            Integer speed = 100;
            Integer currentDirection = 0;
            MapRgvDirection.setRgvDirection();
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            if (direction == null) {
                return ResponseData.error("方向不能为空");
            }
            if (direction == 1) {
                currentDirection = MapRgvDirection.getValue("上");
            } else if (direction == 2) {
                currentDirection = MapRgvDirection.getValue("左");
            } else if (direction == 3) {
                currentDirection = MapRgvDirection.getValue("下");
            } else if (direction == 4) {
                currentDirection = MapRgvDirection.getValue("右");
            }
            if (direction != 1 && direction != 2 && direction != 3 && direction != 4) {
                return ResponseData.error(direction + " 方向不存在");
            }
            try {
                curRgv = SystemInit.getByRgvNo(Integer.parseInt(rgvNo));
            } catch (IllegalStateException e) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
            }
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
            }
            if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
                return ResponseData.error("小车当前状态不可执行按速度行驶指令，请稍后重试");
            }

            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                log.info("接收到按 " + speed + " 速度，方向 " + currentDirection + " 行驶 " + rgvNo + " 号小车的指令");
                RgvInterface rgvCore = ((Rgv60) curRgv).getRgvCore();
                if (direction == 1) {
                    rgvCore.forwardRun();
                } else if (direction == 2) {
                    rgvCore.turnLeft();
                } else if (direction == 3) {
                    rgvCore.fallBackRun();
                } else if (direction == 4) {
                    rgvCore.turnRight();
                }
            } else {
                DirectionStatus rgvDirectionStatus = curRgv.getDirectionStatus();
                if ((currentDirection == 1 || currentDirection == 3) && (rgvDirectionStatus == DirectionStatus.PD_24 || rgvDirectionStatus == DirectionStatus.PD_2)) {
                    return ResponseData.error("小车当前为坡道，请换向后重试");
                }
                if ((currentDirection == 2 || currentDirection == 4) && (rgvDirectionStatus == DirectionStatus.XD_13 || rgvDirectionStatus == DirectionStatus.XD_1)) {
                    return ResponseData.error("小车当前为巷道，请换向后重试");
                }
                log.info("接收到按 " + speed + " 速度，方向 " + currentDirection + " 行驶 " + rgvNo + " 号小车的指令");
                if (RgvMoveBySpeedThread.isSpeedMode(curRgv)) {
                    RgvMoveBySpeedThread.getInstance(curRgv).startSpeedMove(currentDirection, speed);
                } else {
                    ToRes toRes = ToRes.getInstance(curRgv);
                    try {
                        toRes.runWithSpeed(null, currentDirection, speed);
                    } catch (OrderExecuteException e) {
                        return ResponseData.error("按速度 " + speed + " ，方向 " + currentDirection + " 行驶 " + curRgv.getRgvName() + " 失败原因:" + e.getMessage());
                    }
                }
            }
            return ResponseData.success("小车按速度行驶指令发送成功", null);
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("按速度行驶异常:" + e.getMessage());
        }
    }

    /*
     * 按速度停止
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:speedStop')")
    @Log(title = "车辆管理", method = "按速度停止", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/speedStop", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "按速度停止")
    public ResponseData speedStop(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }

            try {
                curRgv = SystemInit.getByRgvNo(rgvNo);
            } catch (IllegalStateException e) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
            }
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
            }
//        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
//            return ResponseData.error("小车当前状态不可执行按速度停止指令，请稍后重试");
//        }
            log.info("接收到按速度停止 " + curRgv.getRgvName() + " 的指令");
            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                RgvInterface rgvCore = ((Rgv60) curRgv).getRgvCore();
                rgvCore.stopManualMove();
            } else {
                if (RgvMoveBySpeedThread.isSpeedMode(curRgv)) {
                    RgvMoveBySpeedThread.getInstance(curRgv).stopSpeedMove();
                } else {
                    ToRes toRes = ToRes.getInstance(curRgv);
                    try {
                        toRes.stopWithSpeed(null);
                    } catch (OrderExecuteException e) {
                        return ResponseData.error("按速度行驶停" + curRgv.getRgvName() + " 失败，错误码：" + e.getMessage());
                    }
                }
            }
            return ResponseData.success("小车按速度停止指令发送成功", null);
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("按速度停止异常:" + e.getMessage());
        }
    }

    /*
     * 按位移行驶
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:distanceRun')")
    @Log(title = "车辆管理", method = "按位移行驶", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/distanceRun", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "按位移行驶")
    public ResponseData distanceRun(@RequestParam Integer rgvNo, @RequestParam Integer distance,
                                    @RequestParam Integer direction) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (distance == null) {
            return ResponseData.error("位移量不能为空");
        }
        if (direction == null) {
            return ResponseData.error("方向不能为空");
        }

        if (direction != 1 && direction != 2 && direction != 3 && direction != 4) {
            return ResponseData.error(direction + " 方向不存在");
        }
        if (distance < 0) {
            return ResponseData.error("位移量不合法");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行按位移行驶指令，请稍后重试");
        }
        if ((direction == 1 || direction == 3) && curRgv.getDirectionStatus() == DirectionStatus.PD_24) {
            return ResponseData.error("小车当前为坡道，请换向后重试");
        }
        if ((direction == 2 || direction == 4) && curRgv.getDirectionStatus() == DirectionStatus.XD_13) {
            return ResponseData.error("小车当前为巷道，请换向后重试");
        }
        log.info("接收到按 " + distance + " 位移量，方向 " + direction + " 行驶 " + rgvNo + " 号小车的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.runWithDstance(null, direction, distance);
        } catch (OrderExecuteException e) {
            return ResponseData.error("按 " + distance + " 位移量，方向 " + direction + " 行驶 " + curRgv.getRgvName() + " 失败，错误码：" + e.getMessage());
        }
        return ResponseData.success("小车按位移量行驶指令发送成功");
    }

    /*
     * 按位移量感应停
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:distanceStop')")
    @Log(title = "车辆管理", method = "按位移量感应停", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/distanceStop")
    @ResponseBody
    @ApiOperation(value = "按位移量感应停")
    public ResponseData distanceStop(@RequestParam Integer rgvNo, @RequestParam Integer distance,
                                     @RequestParam Integer direction) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (distance == null) {
            return ResponseData.error("位移量不能为空");
        }
        if (direction == null) {
            return ResponseData.error("方向不能为空");
        }

        if (direction != 1 && direction != 2 && direction != 3 && direction != 4) {
            return ResponseData.error(direction + " 方向不存在");
        }
        if (distance < 0) {
            return ResponseData.error("位移量不合法");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行按位移感应停指令，请稍后重试");
        }
        if ((direction == 1 || direction == 3) && curRgv.getDirectionStatus() == DirectionStatus.PD_24) {
            return ResponseData.error("小车当前为坡道，请换向后重试");
        }
        if ((direction == 2 || direction == 4) && curRgv.getDirectionStatus() == DirectionStatus.XD_13) {
            return ResponseData.error("小车当前为巷道，请换向后重试");
        }
        log.info("接收到按 " + distance + " 位移量，方向 " + direction + " 行驶 " + curRgv.getRgvName() + " 按位移感应停指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.stopWithDstance(null, direction, distance);
        } catch (OrderExecuteException e) {
            return ResponseData.error("按 " + distance + " 位移量，方向 " + direction + " 行驶 " + curRgv.getRgvName() + " 失败，错误码：" + e.getMessage());
        }
        return ResponseData.success("小车按位移感应停指令发送成功");
    }

    /**
     * 托盘校准
     *
     * @param rgvNo
     * @return
     */
    @Log(title = "车辆管理", method = "托盘校准", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/palletEdit", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "托盘校准")
    public ResponseData palletEdit(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
            }
        } else {
            RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
            if (rgvStatus == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
            }
        }
        log.info("接收到 " + rgvNo + " 号小车的托盘校准指令");
        ToRes toRes = ToRes.getInstance(curRgv);
//		此处发送小车托盘校准指令
        toRes.calibrationPallet(null);
        return ResponseData.success("小车托盘校准指令发送成功");
    }

    /*
     * 换向巷道
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:toTunnel')")
    @Log(title = "车辆管理", method = "换向巷道", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/toTunnel", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "换向巷道")
    public ResponseData toTunnel(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }

        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行换向巷道指令，请稍后重试");
        }

        if (curRgv.getDirectionStatus() == DirectionStatus.XD_13) {
            return ResponseData.error("小车当前为巷道，无需换向");
        }
        log.info("接收到 " + rgvNo + " 号小车的换向巷道指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.changeToRoadway(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 换向巷道失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success("小车换向巷道指令发送成功");
    }

    /**
     * 换向
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:toTurn')")
    @Log(title = "车辆管理", method = "换向", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/toTurn/{rgvNo}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "换向")
    public ResponseData toTurn(@PathVariable Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行换向指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车的换向指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            if (curRgv.getDirectionStatus() == DirectionStatus.PD_24) {
                toRes.changeToRoadway(null);
            } else {
                toRes.changeToRamp(null);
            }
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 换向坡道失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success("小车换向指令发送成功");
    }

    /**
     * 换向坡道
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:toRamp')")
    @Log(title = "车辆管理", method = "换向坡道", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/toRamp", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "换向坡道")
    public ResponseData toRamp(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行换向坡道指令，请稍后重试");
        }
        if (curRgv.getDirectionStatus() == DirectionStatus.PD_24) {
            return ResponseData.error("小车当前为坡道，无需换向");
        }
        log.info("接收到 " + rgvNo + " 号小车的换向坡道指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.changeToRamp(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 换向坡道失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success("小车换向坡道指令发送成功");
    }

    /**
     * 设置小车速度
     *
     * @param rgvNo 小车编号
     * @param speed 速度
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:setSpeed')")
    @Log(title = "车辆管理", method = "设置小车速度", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/setSpeed", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "设置小车速度")
    public ResponseData setSpeed(@RequestParam Integer rgvNo, @RequestParam Integer speed) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (speed == null) {
            return ResponseData.error("速度不能为空");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }

        if (speed > 10000 || speed < 0) {
            return ResponseData.error("速度不合法");
        }
        log.info("接收到 " + rgvNo + " 号小车的设置速度为 " + speed + " 的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.setSpeed(null, speed);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 设置速度 " + speed + " 失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success("小车设置速度指令发送成功");
    }

    /**
     * 打开充电桩
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:openCharge')")
    @Log(title = "车辆管理", method = "打开充电桩", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/openCharge", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "打开充电桩")
    public ResponseData openCharge(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行打开充电桩指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车打开充电桩的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.openCharge(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 打开充电桩失败，错误原因:" + e.getMessage());
        }

        return ResponseData.success(rgvNo + " 号小车打开充电桩指令发送成功");
    }

    /**
     * 打开充电桩
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:startCharge')")
    @Log(title = "车辆管理", method = "一键充电", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/startCharge", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "一键充电")
    public ResponseData startToCharge(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行打开充电桩指令，请稍后重试");
        }
        if (StringUtils.isEmpty(curRgv.getRgvDB().getChargeLocation())) {
            return ResponseData.error("未设置充电位置，无法一键充电！");
        }
        log.info("接收到 " + rgvNo + " 号小车一键充电的指令");
        Node bestNode = Node.parseGrid(curRgv.getRgvDB().getChargeLocation());
        TaskDB task = new TaskDB();
        task.setEndNode(bestNode);
        task.setTaskType(TaskType.CHARGE);
        task.setProcessingRgvNo(curRgv.getRgvDB().getRgvNo());
        task.setRgvProgress(TaskRgvProgress.ASSIGNED_TO_RGV);
        taskdbService.insertTask(Collections.singletonList(task));
        log.info("生成一键充电任务");
        return ResponseData.success(rgvNo + " 号小车打一键充电指令发送成功");
    }

    /**
     * 关闭充电桩
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:closeCharge')")
    @Log(title = "车辆管理", method = "关闭充电桩", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/closeCharge", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "关闭充电桩")
    public ResponseData closeCharge(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行关闭充电桩指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车关闭充电桩的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.closeCharge(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 关闭充电桩失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车关闭充电桩指令发送成功");
    }

    /**
     * 打开蜂鸣器
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:openAlarm')")
    @Log(title = "车辆管理", method = "打开蜂鸣器", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/openAlarm")
    @ResponseBody
    @ApiOperation(value = "打开蜂鸣器")
    public ResponseData openAlarm(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        log.info("接收到 " + rgvNo + " 号小车打开蜂鸣器的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.openAlarm(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 打开蜂鸣器失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车打开蜂鸣器指令发送成功");
    }

    /**
     * 关闭蜂鸣器
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:closeAlarm')")
    @Log(title = "车辆管理", method = "关闭蜂鸣器", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/closeAlarm")
    @ResponseBody
    @ApiOperation(value = "关闭蜂鸣器")
    public ResponseData closeAlarm(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        log.info("接收到 " + rgvNo + " 号小车关闭蜂鸣器的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.closeAlarm(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 关闭蜂鸣器失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车关闭蜂鸣器指令发送成功");
    }

    /*
     * 暂停行驶
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:pauseRun')")
    @Log(title = "车辆管理", method = "暂停行驶", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/pauseRun")
    @ResponseBody
    @ApiOperation(value = "暂停行驶")
    public ResponseData pauseRun(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        log.info("接收到 " + rgvNo + " 号小车暂停行驶的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.pauseRun(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 暂停行驶失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(curRgv.getRgvName() + " 暂停行驶指令发送成功");
    }

    /*
     * 暂停恢复
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:pauseRecover')")
    @Log(title = "车辆管理", method = "暂停恢复", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/pauseRecover")
    @ResponseBody
    @ApiOperation(value = "暂停恢复")
    public ResponseData pauseRecover(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        log.info("接收到 " + rgvNo + " 号小车暂停恢复的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.pauseRecover(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 暂停恢复失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(curRgv.getRgvName() + " 暂停恢复指令发送成功");
    }

    /**
     * 初始化
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:initRgv')")
    @Log(title = "车辆管理", method = "初始化", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/initRgv")
    @ResponseBody
    @ApiOperation(value = "初始化")
    public ResponseData initRgv(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
        }
        log.info("接收到初始化 " + rgvNo + " 号小车的指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            if (curRgv.checkRgvType(RgvType.FIVE_POINT_FOUR_TL)) {
                if (curRgv.isHasDriverError()) {
                    toRes.recoveryDriverError(null);
                }
            }
            curRgv.setCurTask(null);
            toRes.initialize(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 初始化失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(curRgv.getRgvName() + "初始化指令发送成功");
    }

    /**
     * 获取可分配小车
     */
    @GetMapping(value = "/getAvailableRGV")
    @ResponseBody
    @ApiOperation(value = "获取可分配小车")
    public ResponseData getAvailableRGV(@RequestParam String dist) {
        Map<String, List<RgvDB>> map = new HashMap<>();
        map.put("rgvdb", SystemInit.getManualOperRgvs());
        return ResponseData.success("查询成功", map);
    }

    /**
     * 获取在当前层小车的状态
     */
    @GetMapping(value = "/getDistRGVStatus")
    @ResponseBody
    @ApiOperation(value = "获取当前地图小车的状态")
    public ResponseData getDistRGVStatus(@RequestParam String dist) {
        if (StringUtils.isEmpty(dist)) {
            return ResponseData.error("参数有误");
        }
        Map<String, List<DistRGVStatusBO>> map = new HashMap<>();
        map.put("rgvdb", rgvdbService.getDistRGVStatus(dist));
        return ResponseData.success("查询成功", map);
    }

    /**
     * 获取所有小车列表
     */
    @RequestMapping(value = "/getAllRGV", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "获取所有小车")
    public TableDataInfo getAllRGV() {
        startPage();
        List<RgvDB> rgvList = rgvdbService.list();
        return getDataTable(rgvList);
    }

    /**
     * 获取小车信息状态
     */
    @RequestMapping(value = "/getRgvStatus", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "获取小车信息状态")
    @ApiImplicitParams(@ApiImplicitParam(name = "rgvNo", value = "小车rgvNo"))
    public ResponseData getRgvStatus(@RequestParam Integer rgvNo) {
        RgvDB rgv = rgvdbService.getRgvDBByNo(rgvNo);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rgvdb", rgv);
        return ResponseData.success(map);
    }

    /**
     * 故障恢复
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:resetRgv')")
    @Log(title = "车辆管理", method = "故障恢复", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/resetRgv", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "故障恢复")
    @ApiImplicitParams(@ApiImplicitParam(name = "rgvNo", value = "小车rgvNo"))
    public ResponseData resetRgv(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
            if (curRgv.getRgvStatus() != RgvStatus.ERROR) {
                return ResponseData.error("当前小车无故障");
            }
        }
        if (curRgv.getCurLocation() == null) {
            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                return ResponseData.error("请确认小车定位, 如果车不在码点上，请先手动开到码点");
            } else {
                return ResponseData.error("请先同步小车位置");
            }
        }
        log.info("接收到 " + rgvNo + " 号小车故障恢复的指令");
        try {
            curRgv.setInterrupt(false);
            ToRes toRes = ToRes.getInstance(curRgv);
            toRes.initialize(null);

            if (curRgv.checkRgvType(RgvType.FIVE_POINT_FOUR_TL)) {
                if (curRgv.isHasDriverError()) {
                    toRes.recoveryDriverError(null);
                }
            }

            toRes.manualCalibration(null);
            if (curRgv.getRgvDB().getRgvType() == RgvType.FIVE_POINT_FOUR_TL.getValue()) {
                curRgv.getTaskAction().initStatus();
            } else if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                ((Rgv60) curRgv).resetRgv();
            }
            curRgv.setRgvStatus(RgvStatus.READY);
            curRgv.setErrorMessage(null);
            if (curRgv.checkRgvType(RgvType.FIVE_POINT_FOUR_TL)) {
                curRgv.getTaskAction().initStatus();
            }
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 故障恢复失败，错误原因:" + e.getMessage());
        } catch (IOException e) {
            return ResponseData.error(curRgv.getRgvName() + "故障恢复时通讯失败");
        }
        return ResponseData.success(rgvNo + " 号小车故障已恢复");
    }

    /**
     * 托盘顶升
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:upBar')")
    @Log(title = "车辆管理", method = "托盘顶升", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/upBar", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "托盘顶升")
    public ResponseData upBar(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
            }
            if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
                return ResponseData.error("小车当前状态不可执行托盘顶升指令，请稍后重试");
            }
        } else {
            RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
            if (rgvStatus == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
            }
            if (rgvStatus != RgvStatus.READY) {
                return ResponseData.error("子车当前状态不可执行托盘顶升指令，请稍后重试");
            }
        }
        log.info("接收到 " + rgvNo + " 号小车托盘顶升的指令");
        try {
            ToRes.getInstance(curRgv).palletUp(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 托盘顶升失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车托盘顶升指令发送成功");
    }

    /*
     * 托盘下降
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:downBar')")
    @Log(title = "车辆管理", method = "托盘下降", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/downBar", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "托盘下降")
    public ResponseData downBar(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
            }
            if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
                return ResponseData.error("小车当前状态不可执行托盘下降指令，请稍后重试");
            }
        } else {
            RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
            if (rgvStatus == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
            }
            if (rgvStatus != RgvStatus.READY) {
                return ResponseData.error("子车当前状态不可执行托盘下降指令，请稍后重试");
            }
        }
        log.info("接收到 " + rgvNo + " 号小车托盘下降的指令");
        try {
            ToRes.getInstance(curRgv).palletDown(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 托盘下降失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(curRgv.getRgvName() + " 托盘下降指令发送成功");
    }

    /**
     * 同步小车位置
     *
     * @param rgvNo  小车编号
     * @param nodeId 节点编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:synLocation')")
    @Log(title = "车辆管理", method = "同步小车位置", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/synLocation")
    @ResponseBody
    @ApiOperation(value = "同步小车位置")
    public ResponseData synLocation(@RequestParam Integer rgvNo, @RequestParam String nodeId) {
        Rgv curRgv;
        NodeDB nodedb;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (nodeId == null) {
            return ResponseData.error("尚未标记位置, 不能同步");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error(rgvNo + " 号小车不存在");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)
                && curRgv.getRgvStatus() != RgvStatus.ERROR) {
            return ResponseData.error(rgvNo + " 号小车状态为：" + curRgv.getRgvStatus()
                    + "，无法同步！只有就绪或故障状态才可同步");
        }
        if (!curRgv.isSameMapVersion() && curRgv.getRgvDB().getRgvType() == RgvType.FOUR_GENERATIONS.getValue()) {
            return ResponseData.error(rgvNo + " 号小车地图版本不一致");
        }
        nodedb = nodedbServiceImpl.getById(nodeId);
        if (nodedb == null) {
            return ResponseData.error("货位号为 " + nodeId + " 的货位不存在");
        }
        if (nodedb.getGridType().equals(NodeType.ST)) {
            return ResponseData.error("小车不可同步到工位位置!");
        }
        if (nodedb.getGridType().equals(NodeType.B)) {
            return ResponseData.error("小车不可同步到禁用位置!");
        }
        if (nodedb.getGridType().equals(NodeType.L)) {
            LifterOper hoistOper = PlcUnit.getLifterOper(new Coord(nodedb.getGridx(), nodedb.getGridy(), nodedb.getGridz()));
            if (hoistOper == null) {
                return ResponseData.error("提升机未上线不可同步到提升机内！");
            }
            if (!hoistOper.isArrived()) {
                return ResponseData.error("提升机平台未到位无法同步小车！");
            }
            if (nodedb.getGridz() != hoistOper.getHoistCurrentLayer()) {
                return ResponseData.error("同步位置与提升机平台不一致！");
            }
        }

        //小车目标位置点
        Node node = new Node(nodedb.getGridx(), nodedb.getGridy(), nodedb.getGridz());
        if (node.equals(curRgv.getCurLocation())) {
            return ResponseData.error("小车已在当前坐标，无需定位");
        }

//        RouteFactoryImp routeFactoryStartFloor = new RouteFactoryImp(nodedbServiceImpl.getNodeList(),
//                LockNodeManager.getLockedNodes(), null, curRgv.getRgvDB().getRgvType());

        boolean banSyn = nodedbServiceImpl.getNode(node).getNodeType().equals(NodeType.B);
        boolean canStopSyn = nodedbServiceImpl.getNode(node).getCanStop();

        if (banSyn) {
            return ResponseData.error("坐标为 " + node.toString() + " 的节点为禁用节点");
        }

        if (!canStopSyn) {
            return ResponseData.error("坐标为 " + node.toString() + " 的节点为禁止停车节点");
        }

        Set<Coord> nodeSet = new HashSet<Coord>();
        nodeSet.add(node);
        if (LockNodeManager.checkNodesLocked(nodeSet, curRgv)) {
            return ResponseData.error("坐标为 " + node.toString() + " 的节点已被占用");
        }
        log.info("接收到 " + rgvNo + " 号小车同步位置至 " + nodeId + " 指令");
        ToRes toRes = ToRes.getInstance(curRgv);
        try {
            toRes.changeLocation(null, node);

            curRgv.getRgvDB().setLocation(curRgv.getCurLocation().toString());
            rgvdbService.updateRgvLocation(curRgv.getRgvDB());
            LockNodeManager.updateLocationLock(curRgv);

            Set<Coord> unlockSet = LockNodeManager.getLockCoordByObj(curRgv);
            unlockSet.removeAll(nodedbServiceImpl.getLinkedNode(curRgv.getCurLocation()));
            log.info("需要释放的路径资源为：" + unlockSet);
            LockNodeManager.removeLockedNodes(unlockSet, curRgv);
            if (!node.equals(curRgv.getRgvDB().getLocationNode())) {
                WCSNodeModule.cleanWcsNodeModuleMapCacheNodeBy(node);
            }

        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 定位失败，错误原因:" + e.getMessage());
        }
        rgvdbService.updateById(curRgv.getRgvDB());
        //系统是否允许同层多车
        boolean moreToOne1 = WareHouseDBService.getMoreForOne();
        // 不允许同层多车情况下,给当前层上锁
        if (!moreToOne1) {
            LockFloorManager.updateLocationLock(curRgv);
        }
        return ResponseData.success(curRgv.getRgvName() + "位置同步完成");
    }

    /**
     * 同步时间
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:syncTime')")
    @Log(title = "车辆管理", method = "时间同步", businessType = BusinessType.UPDATE)
    @GetMapping(value = "/syncTime")
    @ResponseBody
    @ApiOperation(value = "时间同步")
    public ResponseData syncTime(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行同步时间指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车同步时间的指令");
        try {
            ToRes.getInstance(curRgv).syncTime(null);
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 同步时间失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(curRgv.getRgvName() + " 同步时间指令发送成功");
    }

    /**
     * 中断RGV
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:interruptRgv')")
    @Log(title = "车辆管理", method = "中断RGV", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/interruptRgv/{rgvNo}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "中断RGV")
    public ResponseData interruptRgv(@PathVariable Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            if (((RgvSM) curRgv).getRgvCore().getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
            }
        } else {
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
            }
        }
        curRgv.setRgvStatus(RgvStatus.ERROR);
        curRgv.setInterrupt(true);
        curRgv.setErrorMessage("手动中断！");
        return ResponseData.success(curRgv.getRgvName() + " 中断指令发送成功");
    }

    /**
     * 获取工作区域
     *
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:query')")
    @GetMapping(value = "/getArea")
    @ResponseBody
    @ApiOperation(value = "获得仓库x,y,z坐标的范围")
    public ResponseData getArea() {
        Integer maxX = nodedbServiceImpl.getMaxX();
        Integer maxY = nodedbServiceImpl.getMaxY();
        Integer maxZ = nodedbServiceImpl.getMaxZ();
        HashMap<String, Object> areaMap = new HashMap<>();
        ArrayList<Integer> xList = new ArrayList<>();
        ArrayList<Integer> yList = new ArrayList<>();
        ArrayList<Integer> zList = new ArrayList<>();
        for (Integer i = 1; i <= maxX; i++) {
            xList.add(i);
        }
        for (Integer i = 1; i <= maxY; i++) {
            yList.add(i);
        }
        for (Integer i = 1; i <= maxZ; i++) {
            zList.add(i);
        }
        areaMap.put("xList", xList);
        areaMap.put("yList", yList);
        areaMap.put("zList", zList);
        return ResponseData.success(areaMap);
    }

    /**
     * 提取日志
     *
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:extractLogFile')")
    @GetMapping(value = "/extractLogFile")
    @ResponseBody
    @ApiOperation(value = "提取日志")
    public ResponseData extractLogFile(@RequestParam String fileName, @RequestParam Integer rgvNo) {
        try {
            Rgv rgv = SystemInit.getByRgvNo(rgvNo);

            if (rgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error(rgv.getRgvName() + "离线，不能提取日志");
            }
            if (rgv.getRgvStatus() != RgvStatus.READY) {
                return ResponseData.error(rgv.getRgvName() + "未就绪，不能提取日志");
            }

            ToRes toRes = ToRes.getInstance(rgv);
            try {
                if (rgv.isExtractLogFlag()) {
                    throw new RuntimeException("当前有日志正在提取!");
                }

                if (rgv.isUpdateFirewareFlag()) {
                    throw new RuntimeException("当前正在下载固件!");
                }

                rgv.setExtractLogFlag(true);
                //先发送指令，再提取文件
                if (fileName.equals("LogKCS")) {
                    toRes.sendExtractKcsLog(null);
                } else if (fileName.equals("LogKCSBackUp")) {
                    toRes.sendExtractKcsBackUpLog(null);
                } else if (fileName.equals("LogPulseOilpump")) {
                    toRes.sendExtractOilPumpLog(null);
                } else if (fileName.equals("LogPulseOilpumpBackUp")) {
                    toRes.sendExtractOilPumpBackUpLog(null);
                } else if (fileName.equals("LogPulseTravel")) {
                    toRes.sendExtractDriverLog(null);
                } else if (fileName.equals("LogPulseTravelBackUp")) {
                    toRes.sendExtractDriverBackUpLog(null);
                } else if (fileName.equals("LogWCS")) {
                    toRes.sendExtractWcsLog(null);
                } else if (fileName.equals("LogWCSBackUp")) {
                    toRes.sendExtractWcsBackUpLog(null);
                } else {
                    throw new RuntimeException("不支持该日志的提取");
                }
                RgvExtractLog.extractLog(rgv, fileName);
            } catch (RuntimeException e) {
                LoggerUtil.error("提取" + fileName + "失败，错误原因:" + e.getMessage(), this.getClass());
                return ResponseData.error("提取" + fileName + "失败，错误原因:" + e.getMessage());
            } catch (IOException e) {
                LoggerUtil.error("提取" + fileName + "失败，与RES通讯异常", this.getClass());
                return ResponseData.error("提取" + fileName + "失败，与RES通讯异常");
            } finally {
                rgv.setExtractLogFlag(false);
            }
            return ResponseData.success(fileName + ".log");
        } catch (Exception e) {
            WcsUtil.exceptionLog(e, this.getClass());
            return ResponseData.error(e.getMessage());
        }
    }

    /**
     * 更新固件
     *
     * @param firmWareType : 1(res固件)，2(行驶固件)，3(油泵固件)
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:updateFirmware')")
    @PostMapping(value = "/updateFirmware", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    @ApiOperation(value = "更新固件")
    public ResponseData updateFirmware(@RequestParam MultipartFile file, @RequestParam List<Integer> rgvNo,
                                       @RequestParam Integer firmWareType) {
        try {
            List<Rgv> rgvs = new ArrayList<>();
            List<Integer> errorRgvNos = new ArrayList<>();

            String name = file.getOriginalFilename();
            if (firmWareType == 1) {
                if (!name.startsWith("RES+")) {
                    return ResponseData.error("请选择正确的RES固件");
                }
            } else if (firmWareType == 2) {
                if (!name.startsWith("X34C")) {
                    return ResponseData.error("请选择正确的RES固件");
                }
            } else if (firmWareType == 3) {
                if (!name.startsWith("09B")) {
                    return ResponseData.error("请选择正确的RES固件");
                }
            } else {
                return ResponseData.error("错误的固件类型：" + firmWareType + ", 请联系技术人员升级前端！");
            }

            if (rgvNo.size() == 0) {
                return ResponseData.error("请选择小车");
            }

            for (Integer no : rgvNo) {
                Rgv rgv = SystemInit.getByRgvNo(no);

                if (rgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                    errorRgvNos.add(no);
                    continue;
                }
                if (rgv.getRgvStatus() != RgvStatus.READY) {
                    errorRgvNos.add(no);
                    continue;
                }

                rgvs.add(rgv);
            }

            StringBuffer sb = new StringBuffer();
            for (Rgv curRgv : rgvs) {
                if (curRgv.isUpdateFirewareFlag()) {
                    //小车在下载固件货提取日志中
                    errorRgvNos.add(curRgv.getRgvDB().getRgvNo());
                    WcsUtil.notification(curRgv.getRgvName() + "当前正在下载固件，请稍后再更新固件",
                            NotificationTypeEnum.ERROR);
                    continue;
                }

                if (curRgv.isExtractLogFlag()) {
                    //小车在下载固件货提取日志中
                    WcsUtil.notification(curRgv.getRgvName() + "当前正在提取日志，请稍后再更新固件",
                            NotificationTypeEnum.ERROR);
                    continue;
                }

                ToRes toRes = ToRes.getInstance(curRgv);
                curRgv.setUpdateFirewareFlag(true);
                try {
                    //先发送指令，再传递文件
                    if (firmWareType == 1) {
                        toRes.sendResFirmware(null);
                    } else if (firmWareType == 2) {
                        toRes.sendDriverFirmware(null);
                    } else if (firmWareType == 3) {
                        toRes.sendOilPumpFirmware(null);
                    } else {
                        return ResponseData.error("错误的固件类型：" + firmWareType + ", 请联系技术人员升级前端！");
                    }
                    toRes.updateFirmware(name, file.getInputStream());
                } catch (OrderExecuteException e) {
                    errorRgvNos.add(curRgv.getRgvDB().getRgvNo());
                    LoggerUtil.error(curRgv.getRgvName() + "固件更新 " + " 失败，错误原因:" + e.getMessage(), this.getClass());
                    WcsUtil.notification(curRgv.getRgvName() + "固件更新 " + " 失败，错误原因:" + e.getMessage(),
                            NotificationTypeEnum.ERROR);
                } catch (IOException e) {
                    errorRgvNos.add(curRgv.getRgvDB().getRgvNo());
                    LoggerUtil.error(curRgv.getRgvName() + "固件更新 " + " 失败，与RES通讯异常", this.getClass());
                    WcsUtil.notification(curRgv.getRgvName() + "固件更新 " + " 失败，与RES通讯异常",
                            NotificationTypeEnum.ERROR);
                } finally {
                    curRgv.setUpdateFirewareFlag(false);
                }
            }

            if (errorRgvNos.size() == rgvNo.size()) {
                return ResponseData.error("更新固件失败，具体信息请查看小铃铛!");
            } else if (errorRgvNos.size() > 0) {
                return ResponseData.success("固件更新成功, 重启小车后生效;" + WcsUtil.listToString(errorRgvNos) + "号小车，更新失败，具体信息请查看小铃铛!");
            }
            return ResponseData.success("固件更新成功, 重启小车后生效");
        } catch (Exception e) {
            WcsUtil.exceptionLog(e, this.getClass());
            return ResponseData.error(e.getMessage());
        }
    }

    /**
     * 修改小车编号
     *
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:changeRgvNo')")
    @GetMapping(value = "/changeRgvNo")
    @ResponseBody
    @ApiOperation(value = "修改小车编号")
    public ResponseData changeRgvNo(@RequestParam Integer rgvNo) {
        return ResponseData.success();
    }

    @RequestMapping(value = "/getMapName", method = RequestMethod.GET)
    @ResponseBody
    public ResponseData getMapName() {
        List<String> mapNames = new ArrayList<>();
        Map<Integer, String> mapMsg = RgvInstance.rgvMapManage.getMap();
        for (String mapName : mapMsg.values()) {
            mapNames.add(mapName);
        }
        return ResponseData.success(mapNames);
    }

    @ApiOperation(value = "生成Agv地图")
    @GetMapping("/generateAgvMap")
    public ResponseData generateAgvMap(String mapName, Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在！");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线！");
        }
        if (curRgv.getRgvStatus() != RgvStatus.READY) {
            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                if (curRgv.getRgvStatus() == RgvStatus.UNKNOWN) {
                    return ResponseData.error("设备号为 " + rgvNo + " 的小车没有控制权！");
                }
            } else {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车未就绪！");
            }
        }
        if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
            try {
                String warehouseName = WareHouseDBService.getCurWareHouseDB().getWarehouseName();
                Rgv60 rgv = (Rgv60) curRgv;
                String mapJson = rgv.getRgvCore().downloadMap(mapName);
                String paperFilePath = WcsFuncUtil.getPaperFilePath(ModuleType.RGV_60, warehouseName);
                String mapPath = paperFilePath + File.separator
                        + "wcs_down" + File.separator + mapName + ".smap";
                WcsFuncUtil.writeFile(mapPath, mapJson);
            } catch (IOException e) {
                WcsFuncUtil.exceptionLog(e, this.getClass());
                return ResponseData.error("地图下载 " + curRgv.getRgvName() + " 失败，通讯异常");
            }
        }
        return ResponseData.success(mapName + ".smap");
    }

    @ApiOperation(value = "删除Agv地图")
    @GetMapping("/deleteAgvMap")
    public ResponseData deleteAgvMap(String mapName, Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在！");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线！");
        }
        if (curRgv.getRgvStatus() != RgvStatus.READY) {
            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                if (curRgv.getRgvStatus() == RgvStatus.UNKNOWN) {
                    return ResponseData.error("设备号为 " + rgvNo + " 的小车没有控制权！");
                }
            } else {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车未就绪！");
            }
        }
        if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
            try {
                Rgv60 rgv = (Rgv60) curRgv;
                rgv.getRgvCore().deleteMap(mapName);
            } catch (IOException e) {
                WcsFuncUtil.exceptionLog(e, this.getClass());
                return ResponseData.error("地图下载 " + curRgv.getRgvName() + " 失败，通讯异常");
            }
        }
        return ResponseData.success("地图删除成功");
    }

    @ApiOperation(value = "小车地图导出")
    @GetMapping("/downloadMap")
    public void exportMap(String mapName, HttpServletResponse response) {
        try {
            String warehouseName = WareHouseDBService.getCurWareHouseDB().getWarehouseName();
            String paperFilePath = WcsFuncUtil.getPaperFilePath(ModuleType.RGV_60, warehouseName);
            String mapPath = paperFilePath + File.separator + "wcs_down" + File.separator + mapName + ".smap";
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, mapPath);
            FileUtils.writeBytes(mapPath, response.getOutputStream());
        } catch (Exception e) {
            log.error("导出地图失败", e);
        }
    }


    /**
     * 小车日志下载请求
     *
     * @param fileName 文件名称
     * @param delete   是否删除
     */
    @ApiOperation(value = "小车日志下载请求")
    @GetMapping("/download")
    public void fileDownload(String fileName, int rgvNo, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        try {
            if (!FileUtils.checkAllowDownload(fileName)) {
                throw new Exception(com.suray.commin.core.utils.StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String realFileName = fileName.substring(fileName.indexOf("_") + 1);
            String filePath = System.getProperty("user.dir") + File.separator + "rgv_log" + File.separator +
                    rgvNo + "号小车" + File.separator + fileName;

            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete) {
                FileUtils.deleteFile(filePath);
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 获取控制权
     *
     * @param rgvNo
     * @param hasAuthor ： 获取/释放 控制权
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:changeAuthor')")
    @GetMapping(value = "/changeAuthor")
    @ResponseBody
    @ApiOperation(value = "获取控制权")
    public ResponseData changeAuthor(@RequestParam Integer rgvNo, @RequestParam Boolean hasAuthor) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                Rgv60Interface rgv60 = ((Rgv60) curRgv).getRgvCore();
                rgv60.changeAuthor(hasAuthor);
                if (hasAuthor) {
                    rgv60.action(Order.MANUAL_CALIBRATION);
                }
            } else {
                return ResponseData.error("编号为" + rgvNo + "的小车, 不是6代车, 不支持修改权限");
            }

            return ResponseData.success("获取/释放 控制权成功");
        } catch (IOException e) {
            return ResponseData.error("获取/释放 控制权通讯异常");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("获取/释放 控制权失败:" + e.getMessage());
        }
    }

    /**
     * 重定位
     *
     * @param rgvNo
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:resetPosition')")
    @GetMapping(value = "/resetPosition")
    @ResponseBody
    @ApiOperation(value = "重定位")
    public ResponseData resetPosition(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                Rgv60Interface rgv60Interface = ((Rgv60) curRgv).getRgvCore();
                rgv60Interface.resetPosition();
            } else {
                return ResponseData.error("编号为" + rgvNo + "的小车, 不是6代车, 不支持重定位");
            }

            return ResponseData.success("重定位成功");
        } catch (IOException e) {
            return ResponseData.error("重定位通讯异常");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("重定位失败:" + e.getMessage());
        }
    }

    /**
     * 滚筒左转取货
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:turnLeftToPickUp')")
    @Log(title = "车辆管理", method = "滚筒左转取货", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/turnLeftToPickUp", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "滚筒左转取货")
    public ResponseData turnLeftToPickUp(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行滚筒指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车滚筒左转取货的指令");
        try {
            if (curRgv.checkRgvType(RgvType.RGV_ROLLER)) {
                RgvRollerInterface rgvRollerInterface = ((RgvRoller) curRgv).getRgvCore();
                rgvRollerInterface.action(Order.PALLET_UP, 1);
            } else {
                return ResponseData.error("编号为" + rgvNo + "的小车, 不是滚筒车");
            }
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 滚筒左转取货失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车滚筒左转取货指令发送成功");
    }

    /**
     * 滚筒左转放货
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:turnLeftToRelease')")
    @Log(title = "车辆管理", method = "滚筒左转放货", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/turnLeftToRelease", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "滚筒左转放货")
    public ResponseData turnLeftToRelease(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行滚筒指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车滚筒左转放货的指令");
        try {
            if (curRgv.checkRgvType(RgvType.RGV_ROLLER)) {
                RgvRollerInterface rgvRollerInterface = ((RgvRoller) curRgv).getRgvCore();
                rgvRollerInterface.action(Order.PALLET_DOWN, 1);
            } else {
                return ResponseData.error("编号为" + rgvNo + "的小车, 不是滚筒车");
            }
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 滚筒左转放货失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车滚筒左转放货指令发送成功");
    }

    /**
     * 滚筒右转取货
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:turnRightToPickUp')")
    @Log(title = "车辆管理", method = "滚筒右转取货", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/turnRightToPickUp", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "滚筒右转取货")
    public ResponseData turnRightToPickUp(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行滚筒指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车滚筒右转取货取货的指令");
        try {
            if (curRgv.checkRgvType(RgvType.RGV_ROLLER)) {
                RgvRollerInterface rgvRollerInterface = ((RgvRoller) curRgv).getRgvCore();
                rgvRollerInterface.action(Order.PALLET_UP, 2);
            } else {
                return ResponseData.error("编号为" + rgvNo + "的小车, 不是滚筒车");
            }
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 滚筒右转取货失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车滚筒右转取货指令发送成功");
    }

    /**
     * 滚筒右转放货
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:turnRightToRelease')")
    @Log(title = "车辆管理", method = "滚筒右转放货", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/turnRightToRelease", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "滚筒右转放货")
    public ResponseData turnRightToRelease(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行滚筒指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车滚筒右转放货的指令");
        try {
            if (curRgv.checkRgvType(RgvType.RGV_ROLLER)) {
                RgvRollerInterface rgvRollerInterface = ((RgvRoller) curRgv).getRgvCore();
                rgvRollerInterface.action(Order.PALLET_DOWN, 2);
            } else {
                return ResponseData.error("编号为" + rgvNo + "的小车, 不是滚筒车");
            }
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 滚筒右转放货失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车滚筒右转放货指令发送成功");
    }

    /**
     * 滚筒停止
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:stopRoller')")
    @Log(title = "车辆管理", method = "滚筒停止", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/stopRoller", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "滚筒停止")
    public ResponseData stopRoller(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车离线");
        }
        if (!(curRgv.getRgvResStatus() == RgvStatus.READY || curRgv.getRgvResStatus() == RgvStatus.CHARGING)) {
            return ResponseData.error("小车当前状态不可执行滚筒指令，请稍后重试");
        }
        log.info("接收到 " + rgvNo + " 号小车滚筒停止的指令");
        try {
            if (curRgv.checkRgvType(RgvType.RGV_ROLLER)) {
                ToRes toRes = ToRes.getInstance(curRgv);
                toRes.stopRoller();
            } else {
                return ResponseData.error("编号为" + rgvNo + "的小车, 不是滚筒车");
            }
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 滚筒停止失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号小车滚筒停止指令发送成功");
    }


    /**
     * 切换Agv层
     *
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:changeLayer')")
    @Log(title = "车辆管理", method = "切换Agv层", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/changeLayer", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "切换Agv层")
    public ResponseData changeLayer(Integer layer, Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在！");
        }
        if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线！");
        }
        if (curRgv.getRgvStatus() != RgvStatus.READY) {
            if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                if (curRgv.getRgvStatus() == RgvStatus.UNKNOWN) {
                    return ResponseData.error("设备号为 " + rgvNo + " 的小车没有控制权！");
                }
            } else {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车未就绪！");
            }
        }
        if (curRgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
            try {
               /* Node lifterNode = curRgv.getCurLocation();
                if(curRgv.getCurLocation().getNodeType() == NodeType.L){
                    if(layer != PlcUnit.getLifterOper(lifterNode).getHoistCurrentLayer()){
                        return ResponseData.error("切换层与提升机层不一致,禁止切换");
                    }
                }*/
                Rgv60 rgv = (Rgv60) curRgv;
                rgv.getRgvCore().changeMap(layer);
            } catch (IOException e) {
                WcsFuncUtil.exceptionLog(e, this.getClass());
                return ResponseData.error("切换地图失败" + curRgv.getRgvName() + " 失败，通讯异常");
            }
        } else {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是6代车");
        }
        return ResponseData.success("切换地图成功");
    }

    /**
     * 子车充电
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:startSonCharge')")
    @Log(title = "车辆管理", method = "子车充电", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/startSonCharge", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "子车充电")
    public ResponseData startSonCharge(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
        }
        RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
        if (rgvStatus == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
        }
        if (curRgv.getRgvStatus() != RgvStatus.CHARGING) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不在充电状态，子车不能充电");
        }
        if (rgvStatus != RgvStatus.READY) {
            return ResponseData.error("小车当前状态不可执行打开充电桩指令，请稍后重试");
        }

        RgvSMInterface rgvSM = ((RgvSM) curRgv).getRgvCore();
        if (rgvSM.getSonRgvStatus() == RgvStatus.CHARGING) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车, 子车母车正在充电中");
        }

        log.info("接收到 " + rgvNo + " 号小车, 子车开启充电的指令");
        try {
            ((RgvSM) curRgv).getRgvCore().sonRgvCharge();
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 子车充电失败，错误原因:" + e.getMessage());
        }

        return ResponseData.success(rgvNo + " 号车 子车充电指令发送成功");
    }

    /**
     * 子车停止充电
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:stopSonCharge')")
    @Log(title = "车辆管理", method = "子车停止充电", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/stopSonCharge", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "子车停止充电")
    public ResponseData stopSonCharge(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
        }
        RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
        if (rgvStatus == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
        }
        if (rgvStatus != RgvStatus.READY) {
            return ResponseData.error("小车当前状态不可执行打开充电桩指令，请稍后重试");
        }

        RgvSMInterface rgvSM = ((RgvSM) curRgv).getRgvCore();
        if (rgvSM.getSonRgvStatus() != RgvStatus.CHARGING) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车, 子车当前未充电");
        }

        log.info("接收到 " + rgvNo + " 号小车, 子车停止充电的指令");
        try {
            rgvSM.sonRgvStopCharge();
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 子车停止充电失败，错误原因:" + e.getMessage());
        }

        return ResponseData.success(rgvNo + " 号车 子车停止充电指令发送成功");
    }

    /**
     * 子车故障恢复
     *
     * @param rgvNo 小车编号
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:resetSonRgv')")
    @Log(title = "车辆管理", method = "子车故障恢复", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/resetSonRgv", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "子车故障恢复")
    @ApiImplicitParams(@ApiImplicitParam(name = "rgvNo", value = "小车rgvNo"))
    public ResponseData resetSonRgv(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
        }
        RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
        if (rgvStatus == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
        }
        log.info("接收到 " + rgvNo + " 号小车 子车故障恢复的指令");
        try {
            ((RgvSM) curRgv).getRgvCore().sonRgvRecovery();
        } catch (OrderExecuteException e) {
            return ResponseData.error(curRgv.getRgvName() + " 故障恢复失败，错误原因:" + e.getMessage());
        }
        return ResponseData.success(rgvNo + " 号车 子车故障已恢复");
    }

    /**
     * 子车修改行驶参数
     *
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:edit')")
    @Log(title = "车辆管理", method = "修改小车信息", businessType = BusinessType.UPDATE)
    @PostMapping(value = "/setSonParam")
    @ApiOperation(value = "子车修改行驶参数")
    public ResponseData setSonParam(@RequestBody SonRgvParam sonRgvParam) {
        try {
            log.info("接收到 " + sonRgvParam.getRgvNo() + " 号小车 修改行驶参数:" + sonRgvParam);
            Rgv curRgv;
            RgvDB rgvdb = rgvdbService.getRgvDBByNo(sonRgvParam.getRgvNo());
            curRgv = SystemInit.getByRgvNo(rgvdb.getRgvNo());
            if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
                return ResponseData.error("设备号为 " + sonRgvParam.getRgvNo() + " 的小车 不是子母车");
            }

            if (((RgvSM) curRgv).getRgvCore().getSonRgvStatus() != RgvStatus.READY) {
                return ResponseData.error("设备号为 " + sonRgvParam.getRgvNo() + " 的小车子车未就绪");
            }

            ((RgvSM) curRgv).getRgvCore().sonRgvChangeSpeedConfig(sonRgvParam.getSpeed(), sonRgvParam.getSonAc(),
                    sonRgvParam.getSonDc());

            rgvdb.setSonRgvSpeed(sonRgvParam.getSpeed());
            rgvdb.setSonRgvAccSpeed(sonRgvParam.getSonAc());
            rgvdb.setSonRgvDecSpeed(sonRgvParam.getSonDc());
            deviceManagerService.updateById(rgvdb);
            return ResponseData.success("修改成功");
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + sonRgvParam.getRgvNo() + " 的小车不存在", null);
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("修改失败:" + e);
        }
    }

    /**
     * 按速度行驶按照规定速度行驶100
     *
     * @param rgvNo
     * @param direction
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:speedSonGo')")
    @Log(title = "车辆管理", method = "按速度行驶", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/speedSonGo", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "按速度行驶")
    public ResponseData speedSonGo(@RequestParam String rgvNo,
                                   @RequestParam Integer direction) {
        Rgv curRgv;
        Integer speed = 100;
        Integer currentDirection = direction;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }
        if (direction == null) {
            return ResponseData.error("方向不能为空");
        }
        if (direction != 1 && direction != 2 && direction != 3 && direction != 4) {
            return ResponseData.error(direction + " 方向不存在");
        }
        try {
            curRgv = SystemInit.getByRgvNo(Integer.parseInt(rgvNo));
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
        }
        RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
        if (rgvStatus == RgvStatus.OFF_LINE) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
        }
        if (rgvStatus != RgvStatus.READY) {
            return ResponseData.error("小车当前状态不可执行按速度行驶指令，请稍后重试");
        }

        log.info("接收到按速度行驶，方向 " + currentDirection + ", " + rgvNo + " 号小车 子车的指令");
        try {
            ((RgvSM) curRgv).getRgvCore().sonRgvMoveBySpeed(direction);
        } catch (OrderExecuteException e) {
            return ResponseData.error("按速度 " + speed + " ，方向 " + currentDirection + " 行驶 " + curRgv.getRgvName() +
                    " 失败原因:" + e.getMessage());
        }
        return ResponseData.success("按速度行驶指令发送成功", null);
    }

    /**
     * 按速度停止
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:speedSonStop')")
    @Log(title = "车辆管理", method = "按速度停止", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/speedSonStop", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "按速度停止")
    public ResponseData speedSonStop(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        if (rgvNo == null) {
            return ResponseData.error("请选择小车");
        }

        try {
            curRgv = SystemInit.getByRgvNo(rgvNo);
        } catch (IllegalStateException e) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
        }
        if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
            return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
        }
        log.info("接收到按速度停止 " + curRgv.getRgvName() + " 子车 的指令");
        try {
            ((RgvSM) curRgv).getRgvCore().stopSonRgvMoveBySpeed();
        } catch (OrderExecuteException e) {
            return ResponseData.error("按速度行驶停" + curRgv.getRgvName() + " 失败，错误码：" + e.getMessage());
        }
        return ResponseData.success("按速度停止指令发送成功", null);
    }

    /*
     * 子车校准
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:sonCheck')")
    @Log(title = "车辆管理", method = "子车校准", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/sonCheck", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "子车校准")
    public ResponseData sonCheck(@RequestParam Integer rgvNo) {
        Rgv curRgv;
        try {
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            try {
                curRgv = SystemInit.getByRgvNo(rgvNo);
            } catch (IllegalStateException e) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
            }
            if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
            }
            RgvStatus rgvStatus = ((RgvSM) curRgv).getRgvCore().getSonRgvStatus();
            if (rgvStatus == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
            }
            if (rgvStatus != RgvStatus.READY) {
                return ResponseData.error("子车当前状态不可执行手动校准指令，请稍后重试");
            }
            log.info("接收到手动子车校准 " + rgvNo + " 号小车子车的指令");

            RgvSMInterface rgvSMInterface = ((RgvSM) curRgv).getRgvCore();
            rgvSMInterface.sonRgvCalibration();
            return ResponseData.success("子车校准完成");
        } catch (OrderExecuteException e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            String message = e.getMessage();

            if (StringUtils.isEmpty(message)) {
                CodeDBServiceImpl codeDBService = SpringContextHolder.getBean(CodeDBServiceImpl.class);
                message = e.getErrorMessage() + codeDBService.getCodeDescByType(CodeType.RGV_SON_TYPE.getState(),
                        e.getCode());
            }

            return ResponseData.error("子车校准失败：" + message);
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("子车校准失败：" + e.getMessage());
        }
    }

    /**
     * 子车任务清除
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:rgvTaskClear')")
    @Log(title = "车辆管理", method = "子车任务清除", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/rgvTaskClear", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "子车任务清除")
    public ResponseData rgvTaskClear(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            try {
                curRgv = SystemInit.getByRgvNo(rgvNo);
            } catch (IllegalStateException e) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
            }
            if (((RgvSM) curRgv).getRgvCore().getSonRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车子车已离线");
            }
            if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
            }

            log.info("接收到 " + rgvNo + " 号小车子车任务清除的指令");

            ((RgvSM) curRgv).getRgvCore().sonRgvClearTask();
            return ResponseData.success("子车任务清除成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("子车任务清除 失败：" + e.getMessage());
        }
    }

    /**
     * 母车故障清除
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:clearFault')")
    @Log(title = "车辆管理", method = "母车故障清除", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/clearFault", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "母车故障清除")
    public ResponseData clearFault(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            try {
                curRgv = SystemInit.getByRgvNo(rgvNo);
            } catch (IllegalStateException e) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车不存在");
            }
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车已离线");
            }
            if (!curRgv.checkRgvType(RgvType.RGV_SEER_COMM)
            ) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是6代车");
            }

            log.info("接收到 " + rgvNo + " 号小车 故障清除的指令");

            ((Rgv60) curRgv).getRgvCore().clearAllError();
            return ResponseData.success("故障清除 成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("故障清除 失败：" + e.getMessage());
        }
    }

    /**
     * 子车启用
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:changeSonRgvEnable')")
    @Log(title = "车辆管理", method = "子车启用", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/changeSonRgvEnable", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "子车启用")
    public ResponseData changeSonRgvEnable(@RequestParam Integer rgvNo, @RequestParam Boolean isSonRgvEnable) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (!curRgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是子母车");
            }

            RgvSMInterface rgvSMInterface = ((RgvSM) curRgv).getRgvCore();
            if (isSonRgvEnable) {
                rgvSMInterface.enableSonRgv();
            } else {
                rgvSMInterface.disableSonRgv();
            }
            return ResponseData.success("启用/停用 子车成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("启用/停用 子车失败:" + e.getMessage());
        }
    }

    /**
     * 货叉升降
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:forkLift')")
    @Log(title = "车辆管理", method = "货叉升降", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/forkLift", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "货叉升降")
    public ResponseData forkLift(@RequestParam Integer rgvNo, @RequestParam Integer height) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (!curRgv.checkRgvType(RgvType.RGV_FORK)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是叉车");
            }

            if (height == null) {
                return ResponseData.error("请填入升降高度");
            }

            RgvForkInterface rgvForkInterface = ((RgvFork) curRgv).getRgvCore();
            rgvForkInterface.action(Order.FORK_UP, height.floatValue() / 1000);
            return ResponseData.success("货叉升降 成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("货叉升降 失败:" + e.getMessage());
        }
    }

    /**
     * 货叉顶升
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:forkUp')")
    @Log(title = "车辆管理", method = "货叉顶升", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/forkUp", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "货叉顶升")
    public ResponseData forkUp(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (!curRgv.checkRgvType(RgvType.RGV_FORK)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是叉车");
            }

            if (curRgv.getCurLocation() == null) {
                return ResponseData.error("小车没有位置，不能顶升");
            }

            Float forkHeight = nodedbServiceImpl.getNode(curRgv.getCurLocation()).getForkHeight();

            RgvForkInterface rgvForkInterface = ((RgvFork) curRgv).getRgvCore();
            rgvForkInterface.action(Order.FORK_UP, forkHeight);
            return ResponseData.success("货叉顶升 成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("货叉顶升 失败:" + e.getMessage());
        }
    }

    /**
     * 货叉下降
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:forkDown')")
    @Log(title = "车辆管理", method = "货叉下降", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/forkDown", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "货叉下降")
    public ResponseData forkDown(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (!curRgv.checkRgvType(RgvType.RGV_FORK)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是叉车");
            }

            RgvForkInterface rgvForkInterface = ((RgvFork) curRgv).getRgvCore();
            rgvForkInterface.action(Order.FORK_DOWN);
            return ResponseData.success("货叉下降 成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("货叉下降 失败:" + e.getMessage());
        }
    }

    /**
     * 货叉取货
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:forkGetCargo')")
    @Log(title = "车辆管理", method = "货叉取货", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/forkGetCargo", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "货叉取货")
    public ResponseData forkGetCargo(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (!curRgv.checkRgvType(RgvType.RGV_FORK)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是叉车");
            }

            if (curRgv.getCurLocation() == null) {
                return ResponseData.error("小车没有位置，不能取货");
            }

            Float forkHeight = nodedbServiceImpl.getNode(curRgv.getCurLocation()).getForkHeight();


            RgvForkInterface rgvForkInterface = ((RgvFork) curRgv).getRgvCore();
            rgvForkInterface.action(Order.FORK_GET_CARGO, forkHeight);
            return ResponseData.success("货叉取货 成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("货叉取货 失败:" + e.getMessage());
        }
    }

    /**
     * 货叉放货
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:forkPutCargo')")
    @Log(title = "车辆管理", method = "货叉放货", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/forkPutCargo", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "货叉放货")
    public ResponseData forkPutCargo(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return ResponseData.error("请选择小车");
            }
            curRgv = SystemInit.getByRgvNo(rgvNo);

            if (curRgv == null) {
                return ResponseData.error("不存在编号为" + rgvNo + "的小车");
            }

            if (!curRgv.checkRgvType(RgvType.RGV_FORK)) {
                return ResponseData.error("设备号为 " + rgvNo + " 的小车 不是叉车");
            }

            if (curRgv.getCurLocation() == null) {
                return ResponseData.error("小车没有位置，不能取货");
            }

            Float forkHeight = nodedbServiceImpl.getNode(curRgv.getCurLocation()).getForkHeight();


            RgvForkInterface rgvForkInterface = ((RgvFork) curRgv).getRgvCore();
            rgvForkInterface.action(Order.FORK_PUT_CARGO, forkHeight);
            return ResponseData.success("货叉放货 成功");
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error("货叉放货 失败:" + e.getMessage());
        }
    }

    /**
     * 获取子车
     *
     * @return
     */
    @ApiOperation("获取子车")
    @GetMapping(value = "/getSonRgvs")
    @ResponseBody
    public ResponseData getSonRgvs() {
        return ResponseData.success(devicedbServiceImpl.querySonRgvList(NetAddressType.RGV_SON));
    }

    @GetMapping(value = "/getBACmdResultParam")
    @ResponseBody
    @ApiOperation(value = "获取BA命令的执行结果参数")
    public String get8bCmdParam(@RequestParam Integer rgvNo) {
        try {
            Rgv curRgv;
            if (rgvNo == null) {
                return "请选择小车";
            }
            try {
                curRgv = SystemInit.getByRgvNo(rgvNo);
                curRgv.setBA(true);
            } catch (IllegalStateException e) {
                return "设备号为 " + rgvNo + " 的小车不存在";
            }
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return "设备号为 " + rgvNo + " 的小车已离线";
            }
            if (curRgv.getRgvStatus() != RgvStatus.READY) {
                return "设备号为 " + rgvNo + " 的小车未就绪";
            }
            log.info("接收到 " + rgvNo + " 号小车获取BA的指令参数结果");
            ToRes toRes = ToRes.getInstance(curRgv);
            try {
                return toRes.getBACmdParam();
            } catch (Exception e) {
                return "获取BA的指令参数失败:" + e.getMessage();
            }
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return e.getMessage();
        }
    }

    /**
     * 开启或关闭小车校准
     *
     * @param rgvId
     * @return
     */
    @PreAuthorize("@ss.hasPermi('rgvdb:switchCorrect')")
    @PostMapping(value = "/switchCorrect/{isOpen}/{rgvId}")
    @ResponseBody
    @ApiOperation(value = "开关小车校准")
    public ResponseData switchCorrect(@PathVariable boolean isOpen, @PathVariable Integer rgvId) {
        Rgv curRgv = null;
        ToRes toRes = null;
        try {
            if (rgvId == null) {
                return ResponseData.error("请选择小车");
            }
            try {
                curRgv = SystemInit.getByRgvNo(rgvId);
            } catch (IllegalStateException e) {
                return ResponseData.error("设备号为 " + rgvId + " 的小车不存在");
            }
            if (curRgv.getRgvStatus() == RgvStatus.OFF_LINE) {
                return ResponseData.error("设备号为 " + rgvId + " 的小车已离线");
            }
            if (curRgv.getRgvStatus() != RgvStatus.READY) {
                return ResponseData.error("设备号为 " + rgvId + " 的小车未就绪");
            }
            String str = isOpen ? "开启" : "关闭";
            log.info("接收到 " + rgvId + " 号小车" + str + "校准请求");
            toRes = ToRes.getInstance(curRgv);
            try {
                if (isOpen) {
                    toRes.swicthCalibitionMode(null, true);
                } else {
                    toRes.swicthCalibitionMode(null, false);
                }
                return ResponseData.success(isOpen ? "开启" : "关闭" + "小车校准成功!");
            } catch (Exception e) {
                WcsFuncUtil.exceptionLog(e, this.getClass());
                return ResponseData.error("设备号为 " + rgvId + " 的小车发送命令时出现错误:" + e.getMessage());
            }
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return ResponseData.error(e.getMessage());
        }
    }

}
